# import bpy
from typing import List
# from ...libs.functions.basics import rm_ob
from ...addon.naming import FluidLabNaming
from .basic_store_objects import StoredCollections, SoredStrings
from .common_list_methods import FLUIDLAB_CommonList
from ...libs.functions.get_common_vars import get_common_vars
from bpy.types import PropertyGroup, UIList, Object, Collection, Material
from ...libs.functions.modifiers import remove_modifier_from_object
from ...libs.functions.collections import remove_collection_if_is_empty
from .active_mesh_props.props_settings import ActiveMeshItemSettingsProps
from bpy.props import StringProperty, IntProperty, CollectionProperty, BoolProperty, PointerProperty, FloatProperty
from ...libs.functions.geometry_nodes import get_node_index_or_identifier_by as identifier


""" Fluids Mesh List """


class FLUIDLAB_UL_draw_fluids_mesh(UIList):

    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
        
        if not item.id_name:
            layout.prop(item, "remove", text="Clear", icon='X')
            return
        
        ui = get_common_vars(context, get_ui=True)

        layout.use_property_split = False
        left_sect = layout.row(align=True)
        left_sect.alignment = 'LEFT'

        if ui.main_modules == 'EXPORT_IMPORT':
            left_sect.separator(factor=0.5)
            e_checkbox = left_sect.row(align=True)
            e_checkbox.scale_x = 0.3
            e_checkbox.prop(item, "exportable", text=" ")

        if ui.main_modules == 'DYNAMIC_PAINT':
            left_sect.separator()
            left_sect.prop(item, "dp_brusheable", text="")

        # Cuando estoy y no estoy en popups:
        left_sect.prop(item, "label_txt", text="", emboss=False)
    
        # Right Section:
        right_sect = layout.row(align=True)
        right_sect.alignment = 'RIGHT'

        # icono Monitor:
        right_sect.prop(item, "show_viewport", text="", toggle=True, icon='RESTRICT_VIEW_OFF' if item.show_viewport else 'RESTRICT_VIEW_ON')
        
        if ui.main_modules == 'DYNAMIC_PAINT':
            if not item.dp_without_brush:
                clear_canvas_bt = right_sect.row(align=True) 
                clear_canvas_bt.alert = True
                clear_canvas_bt.prop(item, "dp_without_brush", emboss=False, icon='TRASH', icon_only=True)

        if ui.main_modules == 'MESH':
            # Remove icon:
            rm_button = right_sect.row(align=True)
            rm_button.alert = True
            rm_button.prop(item, "remove", text="", emboss=False, icon='X')




class FluidMeshListItem(PropertyGroup):
    
    def label_txt_update(self, context):
        # Para que si cambia el label, renombre el objeto mesh
        if self.ob and self.label_txt:
            if self.label_txt != self.ob.name:
                self.ob.name = self.label_txt

    label_txt: StringProperty(name="Name", update=label_txt_update)

    id_name: StringProperty(name="ID")
    ob: PointerProperty(type=Object)
    mesh_coll: PointerProperty(type=Collection)
    exportable: BoolProperty(default=False)

    # Mask Names --------------------------------------
    masks_names: CollectionProperty(type=SoredStrings)
    def add_mask_name(self, string):
        item = self.masks_names.add()
        item.name = string

    def remove_mask_name(self, index):
        self.masks_names.remove(index)
    
    @property
    def get_mask_names(self):
        return [mask.name for mask in self.masks_names]

    # End Mask Names --------------------------------------

    from_collections_groups: CollectionProperty(type=StoredCollections)

    def add_from_collection(self, new_collection:Collection) -> None:
        # Prevenimos guardar colecciones que ya esten guardadas:
        current_collections = self.get_from_collections
        if new_collection not in current_collections:
            new_coll = self.from_collections_groups.add()
            new_coll.collection = new_collection
    
    @property
    def get_from_collections(self):
        return [coll.get_collection for coll in self.from_collections_groups]


    # Elementos que se le puede poner un Brush de Dynamic Paint:
    dp_brusheable: BoolProperty(name="Brushes", description="Mark the elements that will be assigned a brush", default=False)

    # Para la papelera que elimina el Brush de Dynamic Paint:
    def dp_without_brush_update(self, context):
        if self.dp_without_brush:
            # eliminamos el brush del item actual:
            remove_modifier_from_object(self.ob, 'DYNAMIC_PAINT', False)

    dp_without_brush: BoolProperty(name="Remove", description="Remove Brush", default=True, update=dp_without_brush_update)
        
    def do_remove(self, context):

        item = self
        if not item:
            return
        
        ob = item.ob

        for coll in ob.users_collection:
            coll.objects.unlink(ob)

        # rm_ob(context, ob)
        
        remove_collection_if_is_empty(context, item.mesh_coll)
        remove_collection_if_is_empty(context, FluidLabNaming.MESHES_COLL)

        # Lo quitamos del listado:
        fluid_mesh = get_common_vars(context, get_fluid_mesh=True)
        fluid_mesh.remove_item(self.id_name)
        fluid_mesh.list_index = fluid_mesh.length-1 if not fluid_mesh.is_void else 0 
        
    remove: BoolProperty(
        default=False, 
        update=do_remove
    )

    def use_collision_update(self, context):
        # Activamos/Desactivamos el ojito del collision:
        ob = self.ob
        gn_mod = ob.modifiers.get(FluidLabNaming.GN_MESH_MOD)
        if gn_mod:
            gn_mod.show_viewport = self.show_viewport

    show_viewport: BoolProperty(
        name="Use Collision",
        description="Enable/Disable Collisions",
        default=True,
        update=use_collision_update
    )
    #-------------------------------------------------------------------------
    # Propiedades guardadas en el mesh_item.settings.x:
    #-------------------------------------------------------------------------
    settings: PointerProperty(type=ActiveMeshItemSettingsProps)
    

class FluidMeshList(PropertyGroup, FLUIDLAB_CommonList):

    # Attributes (with or without methods):
    def list_index_update(self, context):
        item = self.active
        if not item:
            return
    
    list_index: IntProperty(name="Layer List", description="The Layer List", default=-1, update=list_index_update)
    list: CollectionProperty(type=FluidMeshListItem)

    # Fluid Mesh List Methods:
    def add_item(self, item_id:str, label_txt:str, mesh_coll:Collection, ob:Object, from_collections_groups:List=None, masks_names:List[str]=[]) -> None:

        item = self.list.add()
        item.id_name = item_id
        item.label_txt = label_txt

        item.ob = ob
        item.mesh_coll = mesh_coll # collection

        # Guardamos las colecciones originales desde donde eligio el usuario crear el mesh:
        if from_collections_groups: 
            [item.add_from_collection(collection) for collection in from_collections_groups]
        
        # Si masks_names tiene elementos, los añadimos a la propiedad masks_names
        if masks_names:
            for mask_name in reversed(masks_names):
                item.add_mask_name(mask_name)
        
        # seteamos el ultimo elemento como activo:
        self.list_index = self.length-1
    

    @property
    def get_all_dp_brusheable(self):
        return [item for item in self.list if item.dp_brusheable]
    